package functionalEnrichment.semanticSimilarity.semanticSimilarityCalculator.units;

import java.util.ArrayList;
import java.util.List;



/**
 * A child of the Gene class that extends the functionality of Gene to allow inclusion
 * of GO annotation in the form of a List Object that contains GoTerm objects. For the sake of
 * memory usage, only the base GO terms (the most specific ones) are stored, parent terms of these can be
 * retrieved by climbing the GoTerm tree, as employed in the <code>getAllTermsIncludingParents()</code> method.
 * @author Jamie MacPherson
 */

public class AnnotatedGene extends Gene{

    // a list of the base GO terms
    private List<GoTerm> terms = new ArrayList<GoTerm>();


    /**
     *
     * @param id performs the same function as the id in the Gene class.
     */
    public AnnotatedGene(String id) {
        super(id);
    }

    /**
     * Gets all the base (most specific) GO terms.
     * @return the list of base GO terms.
     */
    public List<GoTerm> getBaseGoTerms() {
        return terms;
    }

    
    /**
     * Gets all the base GO terms and all of their parents, right up to the root GO term.
     * To do this the <code>addAllParents</code> method is called, this will recursively
     * call itself until all parent terms are added, right up to the root.
     * @return the list of GO terms.
     */
    public List<GoTerm> getAllTermsIncludingParents() {
        List<GoTerm> allTerms = new ArrayList<GoTerm>();
        for(GoTerm gt : terms){
            if(!allTerms.contains(gt)){
                allTerms.add(gt);
                addAllParents(gt, allTerms);
            }
        }
        return allTerms;
    }

    /**
     * This method takes a list of terms and will all of the parents
     * of the specified GoTerm to that list. When a new parent that is not part of the list
     * is found, it is added to the list and the method will recursively call itself until no new
     * terms are added to the list, hence, the list contains all the parent GoTerms, right up to the
     * root node.
     * @param gt the GO term whose parets will be added to the specified list of terms.
     * This term should also be in that list of terms.
     * @param allTerms the list of terms to which parent GO terms are added.
     */
    private void addAllParents(GoTerm gt, List<GoTerm> allTerms) {
        for(GoTerm parent : gt.getParents()){
            if(!allTerms.contains(parent)){
                allTerms.add(parent);
                addAllParents(parent, allTerms);                
            }
        }
    }

}
